﻿/*
COPYRIGHT NOTICE

Copyright (c) 2011, S James S Stapleton
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
	  this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice,
	  this list of conditions and the following disclaimer in the documentation
	  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ConfigFileExplorer
{
    internal class add_ui_elements
    {
        /// <summary>
        /// A configuration key
        /// </summary>
        protected internal TextBox m_key;
        /// <summary>
        /// A configuration value
        /// </summary>
        protected internal TextBox m_val;
        /// <summary>
        /// A configuration comment
        /// </summary>
        protected internal TextBox m_com;
        /// <summary>
        /// Button to click to remove the entry
        /// </summary>
        protected internal Button m_remove;
        /// <summary>
        /// The number of rows for a key
        /// </summary>
        protected internal int m_key_h = 1;
        /// <summary>
        /// The number of rows for a value
        /// </summary>
        protected internal int m_val_h = 2;
        /// <summary>
        /// The number of rows for a comment
        /// </summary>
        protected internal int m_com_h = 3;
        /// <summary>
        /// Click to increase the size of key, taking from val
        /// </summary>
        protected internal Button m_key_val;
        /// <summary>
        /// Click to increase the size of key, taking from com
        /// </summary>
        protected internal Button m_key_com;
        /// <summary>
        /// click to increase the size of val, taking from key
        /// </summary>
        protected internal Button m_val_key;
        /// <summary>
        /// click to increase the size of val taking from com
        /// </summary>
        protected internal Button m_val_com;
        /// <summary>
        /// click to increase the size of com taking from key
        /// </summary>
        protected internal Button m_com_key;
        /// <summary>
        /// click to increase the size of com taking from val
        /// </summary>
        protected internal Button m_com_val;
        /// <summary>
        /// The row of this in the display
        /// </summary>
        protected internal int m_row;

        protected internal TabPage m_parent;

        static protected internal int c_top = 36;
        static protected internal int c_tabindex = 11;
        static protected internal System.Drawing.Size c_btn_size = new System.Drawing.Size(20,20);
        static protected internal System.Drawing.Size c_delbtn_size = new System.Drawing.Size(20,140);

        static protected internal System.Drawing.Image c_up = null;
        static protected internal System.Drawing.Image c_down = null;
        static protected internal System.Drawing.Image c_delete = null;
        static protected internal object c_lock = new object();

        private add_ui_elements(){}

        /// <summary>
        /// Create a new set of UI elements for a given configuration key
        /// </summary>
        /// <param name="parent">The parent form they will be placed in</param>
        /// <param name="pos">How many ui keys are prior to this one</param>
        /// <param name="do_layout">true to handle layout matenance (Suspend/Resume), set to false
        /// and handle these yourself if you have a lot of these to add</param>
        protected internal add_ui_elements(TabPage parent, int pos, bool do_layout)
        {
            if(c_up==null)
            {
                lock(c_lock)
                {
                    if(c_up == null) //only assign once, assure still null
                    {
                        c_up = global::ConfigFileExplorer.Properties.Resources.up;
                        c_down = global::ConfigFileExplorer.Properties.Resources.down;
                        c_delete = global::ConfigFileExplorer.Properties.Resources.delete;
                    }
                }
            }
            this.m_row = pos;
            this.m_parent = parent;
            if(do_layout)
            {
                parent.SuspendLayout();
            }

            this.m_key = new TextBox();
            this.m_val = new TextBox();
            this.m_com = new TextBox();
            this.m_remove = new Button();
            this.m_key_val = new Button();
            this.m_key_com = new Button();
            this.m_val_key = new Button();
            this.m_val_com = new Button();
            this.m_com_key = new Button();
            this.m_com_val = new Button();

            this.m_remove.Size = c_delbtn_size;
            this.m_key_val.Size = c_btn_size;
            this.m_key_com.Size = c_btn_size;
            this.m_val_key.Size = c_btn_size;
            this.m_val_com.Size = c_btn_size;
            this.m_com_key.Size = c_btn_size;
            this.m_com_val.Size = c_btn_size;

            this.m_remove.Click += new EventHandler((object o, EventArgs e) => { this.remove_this(); });

            this.m_key_val.Click += new EventHandler((object o, EventArgs e) => { this.resize_fields(1, 2); });
            this.m_key_com.Click += new EventHandler((object o, EventArgs e) => { this.resize_fields(1, 3); });
            this.m_val_key.Click += new EventHandler((object o, EventArgs e) => { this.resize_fields(2, 1); });
            this.m_val_com.Click += new EventHandler((object o, EventArgs e) => { this.resize_fields(2, 3); });
            this.m_com_key.Click += new EventHandler((object o, EventArgs e) => { this.resize_fields(3, 1); });
            this.m_com_val.Click += new EventHandler((object o, EventArgs e) => { this.resize_fields(3, 2); });

            this.m_key.Multiline = true;
            this.m_val.Multiline = true;
            this.m_com.Multiline = true;
            
            size_text();
            position();

            this.m_remove.Image = c_delete;
            this.m_remove.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter;
            this.m_remove.UseVisualStyleBackColor = true;
            this.m_key_val.Image = c_up;
            this.m_key_val.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter;
            this.m_val_key.Image = c_up;
            this.m_val_key.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter;
            this.m_com_key.Image = c_up;
            this.m_com_key.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter;
            this.m_key_com.Image = c_down;
            this.m_key_com.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter;
            this.m_val_com.Image = c_down;
            this.m_val_com.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter;
            this.m_com_val.Image = c_down;
            this.m_com_val.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter;


            ConfigFileExplorer.me.tt_all.SetToolTip(this.m_remove, "Remove this entry");
            ConfigFileExplorer.me.tt_all.SetToolTip(this.m_key_val, "Take one line from the middle field and add it to the top");
            ConfigFileExplorer.me.tt_all.SetToolTip(this.m_key_com, "Take one line from the bottom field and add it to the top");
            ConfigFileExplorer.me.tt_all.SetToolTip(this.m_val_key, "Take one line from the top field and add it to the middle");
            ConfigFileExplorer.me.tt_all.SetToolTip(this.m_val_com, "Take one line from the bottom field and add it to the middle");
            ConfigFileExplorer.me.tt_all.SetToolTip(this.m_com_key, "Take one line from the top field and add it to the bottom");
            ConfigFileExplorer.me.tt_all.SetToolTip(this.m_com_val, "Take one line from the middle field and add it to the bottom");

            parent.Controls.Add(this.m_key);
            parent.Controls.Add(this.m_val);
            parent.Controls.Add(this.m_com);
            parent.Controls.Add(this.m_remove);
            parent.Controls.Add(this.m_key_val);
            parent.Controls.Add(this.m_key_com);
            parent.Controls.Add(this.m_val_key);
            parent.Controls.Add(this.m_val_com);
            parent.Controls.Add(this.m_com_key);
            parent.Controls.Add(this.m_com_val);

            if(do_layout)
            {
                parent.ResumeLayout(false);
                parent.PerformLayout();

                if(m_parent.VerticalScroll.Enabled ^ ConfigFileExplorer.me.kvp_scroll_wasvis)
                {
                    parent.SuspendLayout();

                    foreach(add_ui_elements e in ConfigFileExplorer.me.add_elements)
                    {
                        e.size_text();
                    }
                    this.size_text();

                    parent.ResumeLayout(false);
                    parent.PerformLayout();
                }
            }
        }

        /// <summary>
        /// Create a new set of UI elements for a given configuration key. Handles UI logistics
        /// </summary>
        /// <param name="parent">The parent form they will be placed in</param>
        /// <param name="pos">How many ui keys are prior to this one</param>
        protected internal add_ui_elements(TabPage parent, int pos) : this(parent, pos, true)
        {
        }

        /// <summary>
        /// Resize the designated fields. 1=key,2=val,3=com
        /// </summary>
        /// <param name="grow">the field to grow by 1</param>
        /// <param name="shrink">the field to shrink by 1</param>
        protected internal void resize_fields(int grow, int shrink)
        {
            bool shrunk = false;
            if(shrink == 1)
            {
                if(this.m_key_h > 1)
                {
                    shrunk = true;
                    this.m_key_h--;
                }
            }
            else if(shrink == 2)
            {
                if(this.m_val_h > 1)
                {
                    shrunk = true;
                    this.m_val_h--;
                }
            }
            else
            {
                if(this.m_com_h > 1)
                {
                    shrunk = true;
                    this.m_com_h--;
                }
            }
            if(shrunk)
            {
                if(grow == 1)
                    this.m_key_h++;
                else if(grow == 2)
                    this.m_val_h++;
                else
                    this.m_com_h++;

                this.size_text();
            }
        }

        protected internal void size_text()
        {
            int pw = this.m_parent.Width;
            if(m_parent.VerticalScroll.Enabled) pw -= 20;
            this.m_key.Size = new System.Drawing.Size(pw - 56, this.m_key_h * 24 - 4);
            this.m_val.Size = new System.Drawing.Size(pw - 56, this.m_val_h * 24 - 4);
            this.m_com.Size = new System.Drawing.Size(pw - 56, this.m_com_h * 24 - 4);
            position_text();
        }

        protected internal void position_text()
        {
            int top;
            if(m_row > 0 && ConfigFileExplorer.me.add_elements.Count > 0)
                top = ConfigFileExplorer.me.add_elements[m_row - 1].m_key.Top + 144;
            else
                top = c_top;

            this.m_key.Location = new System.Drawing.Point(52, top);
            this.m_val.Location = new System.Drawing.Point(52, top + this.m_key_h * 24);
            this.m_com.Location = new System.Drawing.Point(52, top + (this.m_key_h + this.m_val_h) * 24);
        }

        protected internal void position()
        {
            int tab_index = c_tabindex + m_row*11;
            this.m_remove.Name = "btn_remove_" + this.m_row.ToString();
            this.m_remove.TabIndex = tab_index++;
            this.m_key_val.Name = "btn_key_val_" + this.m_row.ToString();
            this.m_key_val.TabIndex = tab_index++;
            this.m_key_com.Name = "btn_key_com_" + this.m_row.ToString();
            this.m_key_com.TabIndex = tab_index++;
            this.m_val_key.Name = "btn_val_key_" + this.m_row.ToString();
            this.m_val_key.TabIndex = tab_index++;
            this.m_val_com.Name = "btn_val_com_" + this.m_row.ToString();
            this.m_val_com.TabIndex = tab_index++;
            this.m_com_key.Name = "btn_com_key_" + this.m_row.ToString();
            this.m_com_key.TabIndex = tab_index++;
            this.m_com_val.Name = "btn_com_val_" + this.m_row.ToString();
            this.m_com_val.TabIndex = tab_index++;
            this.m_key.Name = "txt_key_" + this.m_row.ToString();
            this.m_key.TabIndex = tab_index++;
            this.m_val.Name = "txt_val_" + this.m_row.ToString();
            this.m_key.TabIndex = tab_index++;
            this.m_com.Name = "txt_com_" + this.m_row.ToString();
            this.m_key.TabIndex = tab_index++;
            
            int top;
            if(m_row > 0 && ConfigFileExplorer.me.add_elements.Count > 0)
                top = ConfigFileExplorer.me.add_elements[m_row-1].m_key.Top + 144;
            else
                top = c_top;
            this.m_remove.Location  = new System.Drawing.Point(4,  top);
            this.m_key_val.Location = new System.Drawing.Point(28, top);
            this.m_key_com.Location = new System.Drawing.Point(28, top + 24);
            this.m_val_key.Location = new System.Drawing.Point(28, top + 48);
            this.m_val_com.Location = new System.Drawing.Point(28, top + 72);
            this.m_com_key.Location = new System.Drawing.Point(28, top + 96);
            this.m_com_val.Location = new System.Drawing.Point(28, top + 120);
            position_text();
        }

        /// <summary>
        /// Remove the UI elements. perform layout maintenance.
        /// </summary>
        protected internal void remove_this()
        {
            remove_this(true);
        }
        /// <summary>
        /// Remove the provided UI elements.
        /// </summary>
        /// <param name="handle_layout">Perform layout maintenance (suspend, resume) if true, otherwise do not.</param>
        protected internal void remove_this(bool handle_layout)
        {
            if(handle_layout)
            {
                ConfigFileExplorer.me.SuspendLayout();
                m_parent.SuspendLayout();
            }
            //remove element hooks:
            this.m_parent.Controls.Remove(this.m_key);
            this.m_parent.Controls.Remove(this.m_key_val);
            this.m_parent.Controls.Remove(this.m_key_com);
            this.m_parent.Controls.Remove(this.m_val);
            this.m_parent.Controls.Remove(this.m_val_key);
            this.m_parent.Controls.Remove(this.m_val_com);
            this.m_parent.Controls.Remove(this.m_com);
            this.m_parent.Controls.Remove(this.m_com_val);
            this.m_parent.Controls.Remove(this.m_com_key);
            this.m_parent.Controls.Remove(this.m_remove);

            List<add_ui_elements> all = ConfigFileExplorer.me.add_elements;
            IEnumerator<add_ui_elements> allen = all.GetEnumerator();
            int count = 0;
            while(allen.MoveNext() && this.m_row > count) count++;
            while(allen.MoveNext())
            {
                add_ui_elements aue = allen.Current;
                aue.m_row = count;
                aue.position();
                count++;
            }
            all.RemoveAt(this.m_row);

            m_parent.ResumeLayout(false);
            m_parent.PerformLayout();
            ConfigFileExplorer.me.ResumeLayout(false);
            ConfigFileExplorer.me.PerformLayout();

            if(m_parent.VerticalScroll.Enabled ^ ConfigFileExplorer.me.kvp_scroll_wasvis)
            {
                ConfigFileExplorer.me.SuspendLayout();
                m_parent.SuspendLayout();

                foreach(add_ui_elements e in ConfigFileExplorer.me.add_elements)
                {
                    e.size_text();
                }
                this.size_text();

                if(handle_layout)
                {
                    m_parent.ResumeLayout(false);
                    m_parent.PerformLayout();
                    ConfigFileExplorer.me.ResumeLayout(false);
                    ConfigFileExplorer.me.PerformLayout();
                }
            }
        }
    }
}
